/**
 * CS371P C++ Project Utilities
 * Definition file: ProjectUtil.h
 *
 * @author Jonathan Bernard (jdbernard@gmail.com)
 *
 * This work is copyright 2009 by Jonathan Bernard. All rights reserved.
 * This code is NOT open source (at this time). Redistribution rights are
 * explicitly reserved by Jonathan Bernard. Jonathan Bernard has granted
 * said rights to Lincoln Simmons for the purposes of UT CS371P Project 1
 *
 * @brief This library contains a simple command line parser. Since I wrote
 * this rather quickly, it is not yet documented. It should be by the end of
 * project 2.
 */

#ifndef _PROJECT_UTIL_H
#define _PROJECT_UTIL_H_

#include <iostream>
#include <sstream>
#include <string.h>
#include <stdexcept>

using namespace std;
/*int findInArray(char* arr[], int arrLen, const char* find, int findLen); 

int getValueForOption(char* args[], int argc, const char* option, char* out);*/

class Option {

public:
    Option(const char* shortName);
    ~Option();

    Option &longName(const char* name);
    Option &numArgs(int numArgs);
    Option &description(const char* desc);
    Option &required(bool required);
    bool isSet();
    bool isRequired();
    void getShortName(char* out, int maxlen = -1);
    const char *getShortName();
    void getLongName(char* out, int maxlen = -1);
    const char *getLongName();
    const char *getDescription();
    // TODO: void getDescription(char* out, int maxlen = -1);
    int getNumArgs();
    //void setValues(int maxlen, ...);
    void setValues(char** inValues, int maxlen = -1);
    void getValues(char** out, int maxlen = -1);
    const char *getValue();
    void printShort(ostream& out);
    void print(ostream& out);

private:
    char* _shortName;
    char* _longName;
    char* _description;
    char** _values;
    bool _required;
    int _numArgs;

    void _invalidateValues();
};

class SimpleCli {

public:
    SimpleCli(const char* progName);
    ~SimpleCli();

    Option &makeOption(const char* shortName);
    Option *getOption(const char* shortName);
    int getNumberOfOptions();
    void getOptions(Option** optionsOut);

    void parse(int argc, char* argv[]);
    bool isSet();
    bool isSet(const char * shortName);

    const char* getValue(const char* shortName);
    int getNumberOfArgs();
    void getArgs(char** out, int maxlen = -1);

    void printUsage(ostream&out);

private:

    Option** _options;
    int _capacity;
    int _numOptions;

    // args here represent only those cmdline args which do not
    // belong to an option
    char** _args;       
    int _numArgs;

    char* _progName;

    bool _set;

    void _resize();
    void _invalidateArgs();
    
};
#endif
